package org.tzeng.html.dao;

/**
 * Created by tzeng on 2016-01-04.
 */
import java.util.ArrayList;

import org.apache.commons.lang.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.WriteResult;

//保证线程安全
public class MongodbClient{

    private MongoClient mongoClient = null;

    public MongodbClient(MongodbConfig conf) throws Exception {
        MongoClientOptions.Builder build = new MongoClientOptions.Builder();

        //与目标数据库能够建立的最大connection数量
        build.connectionsPerHost(conf.getMaxBlockNum());
        //如果当前所有的connection都在使用中，则每个connection上可以有50个线程排队等待
        build.threadsAllowedToBlockForConnectionMultiplier(conf.getMaxBlockNum());
		/*
		 * 一个线程访问数据库的时候，在成功获取到一个可用数据库连接之前的最长等待时间为2分钟
		 * 这里比较危险，如果超过maxWaitTime都没有获取到这个连接的话，该线程就会抛出Exception
		 * 故这里设置的maxWaitTime应该足够大，以免由于排队线程过多造成的数据库访问失败
		 */
        build.maxWaitTime(conf.getMaxWaitTime());
        // 与数据库建立连接的timeout
        build.connectTimeout(conf.getConnetcTimeout());

        MongoClientOptions myOptions = build.build();
        String host = conf.getHost();
        if (StringUtils.isNotBlank(host)) {
            mongoClient = new MongoClient(conf.getHost(), myOptions);
        } else {
            throw new Exception("Host is blank");
        }
    }


    public boolean delete(String dbName, String collectionName, String key, String value) {
        return delete(dbName,collectionName,new String[]{ key }, new String[]{ value });
    }
    public boolean delete(String dbName, String collectionName, String[] keys, String[] values) {
        DB db = null;
        DBCollection dbCollection = null;
        if(keys!=null && values!=null) {
            if(keys.length != values.length){   //如果keys和values不对等，直接返回false
                return false;
            } else {
                try {
                    //获取指定的数据库
                    db = mongoClient.getDB(dbName);
                    //获取指定的collectionName集合
                    dbCollection = db.getCollection(collectionName);
                    //构建删除条件
                    BasicDBObject doc = new BasicDBObject();
                    //删除返回结果
                    WriteResult result = null;
                    String resultString = null;
                    //添加删除的条件
                    for(int i=0; i<keys.length; i++){
                        doc.put(keys[i], values[i]);
                    }
                    //执行删除操作
                    result = dbCollection.remove(doc);

                    resultString = result.getError();
                    if(null != db){
                        try {
                            //请求结束后关闭db
                            db.requestDone();
                            db = null;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    //根据删除执行结果进行判断后返回结果
                    return (resultString!=null) ? false : true;
                } finally{
                    if(null != db){
                        //关闭db
                        db.requestDone();
                        db = null;
                    }
                }
            }
        }
        return false;
    }

    public ArrayList<DBObject> find(String dbName, String collectionName,String key, String value) {
        return find(dbName,collectionName,new String[]{key}, new String[]{value});
    }
    public ArrayList<DBObject> find(String dbName, String collectionName,String[] keys, String[] values) {
        //创建返回的结果集
        ArrayList<DBObject> resultList = new ArrayList<DBObject>();
        DB db = null;
        DBCollection dbCollection = null;
        DBCursor cursor = null;
        if(keys!=null && values!=null){
            if(keys.length != values.length){
                //如果传来的查询参数对不对，直接返回空的结果集
                return resultList;
            } else {
                try {
                    db = mongoClient.getDB(dbName);
                    dbCollection = db.getCollection(collectionName);
                    //构建查询条件
                    BasicDBObject queryObj = new BasicDBObject();
                    for(int i = 0; i<keys.length; i++) {
                        queryObj.put(keys[i], values[i]);
                    }

                    cursor = dbCollection.find(queryObj);
                    int count = 0;

                    while(cursor.hasNext()){
                        resultList.add(cursor.next());
                    }
                    return resultList;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally{
                    if(null != cursor){
                        cursor.close();
                    }
                    if(null != db){
                        db.requestDone();//关闭数据库请求
                    }
                }
            }
        }
        return resultList;
    }
    public boolean insert(String dbName, String collectionName, String key, String value) {
        return insert(dbName,collectionName,new String[]{key}, new String[]{value});
    }

    public boolean insert(String dbName, String collectionName, String[] keys, String[] values) {
        DB db = null;
        DBCollection dbCollection = null;
        WriteResult result = null;
        String resultString = null;
        if(keys!=null && values!=null){
            if(keys.length != values.length){
                return false;
            } else {
                db = mongoClient.getDB(dbName);
                dbCollection = db.getCollection(collectionName);
                BasicDBObject insertObj = new BasicDBObject();
                for(int i=0; i<keys.length; i++){
                    insertObj.put(keys[i], values[i]);
                }

                try {
                    result = dbCollection.insert(insertObj);
                    resultString = result.getError();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if(null != db){
                        db.requestDone();//请求结束后关闭db
                    }
                }
                return (resultString != null) ? false : true;
            }
        }
        return false;
    }

    public boolean isExsit(String dbName, String collectionName, String key, String value) {
        DB db = null;
        DBCollection dbCollection = null;
        if(key!=null && value!=null){
            try {
                db = mongoClient.getDB(dbName);
                dbCollection = db.getCollection(collectionName);
                BasicDBObject obj = new BasicDBObject();
                obj.put(key, value);

                if(dbCollection.count(obj) > 0) {
                    return true;
                }else{
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally{
                if(null != db){
                    db.requestDone();  //关闭db
                    db = null;
                }
            }
        }
        return false;
    }

    public boolean update(String dbName, String collectionName,DBObject oldValue, DBObject newValue) {
        DB db = null;
        DBCollection dbCollection = null;
        WriteResult result = null;
        String resultString = null;

        if(oldValue.equals(newValue)){
            return true;
        } else {
            try {
                db = mongoClient.getDB(dbName);
                dbCollection = db.getCollection(collectionName);
                result = dbCollection.update(oldValue, newValue);
                resultString = result.getError();
                return (resultString!=null) ? false : true;
            } catch (Exception e) {
                e.printStackTrace();
            } finally{
                if(null != db){
                    db.requestDone();   //关闭db
                    db = null;
                }
            }
        }
        return false;
    }

}

